package com.basker.pisces.core.meta.bean;

import java.beans.PropertyDescriptor;
import java.sql.JDBCType;

import org.springframework.beans.BeanUtils;

import com.basker.pisces.core.meta.IDataField;
import com.basker.pisces.core.meta.IDataObjectMeta;
import com.basker.pisces.core.meta.annotation.CollectionField;
import com.basker.pisces.core.meta.annotation.DataField;
import com.basker.pisces.core.meta.annotation.ObjectField;
import com.basker.pisces.core.meta.annotation.ReferenceField;
import com.basker.pisces.exception.ExceptionFactory;

class BeanFieldFactory {

    public static BeanCollectionField createCollectionField(BeanFieldDescriptor beanFieldDescriptor,
                                                            CollectionField collectionFieldAnnotation) {
        String name = beanFieldDescriptor.getName();
        String displayName = collectionFieldAnnotation.displayName();
        String fkFieldDescription = collectionFieldAnnotation.fkFieldDescription();

        BeanCollectionField collectionField = new BeanCollectionField(beanFieldDescriptor, name, displayName, null);
        collectionField.setFkFieldDescription(fkFieldDescription);

        return collectionField;
    }

    public static BeanDataField createDataField(BeanFieldDescriptor beanFieldDescriptor) {
        DataField dataFieldAnnotation = (DataField) beanFieldDescriptor.getFieldAnnotation();

        String name = beanFieldDescriptor.getName();

        String displayName = dataFieldAnnotation.displayName();
        String dbFieldName = dataFieldAnnotation.dbFieldName();
        String hostTableName = dataFieldAnnotation.tableName();
        boolean pkField = dataFieldAnnotation.pkField();
        boolean indexField = dataFieldAnnotation.indexField();
        JDBCType jdbcType = dataFieldAnnotation.jdbcType();
        int length = dataFieldAnnotation.length();
        int scale = dataFieldAnnotation.scale();
        boolean cData = dataFieldAnnotation.cData();
        int sort = dataFieldAnnotation.sort();
        String description = dataFieldAnnotation.description();

        BeanDataField dataField = new BeanDataField(beanFieldDescriptor, name, displayName, dbFieldName, hostTableName,
                pkField, indexField, jdbcType);

        if (length > -1) {
            dataField.setLength(length);
        }

        if (scale > -1) {
            dataField.setScale(scale);
        }

        dataField.setSort(sort);
        dataField.setCData(cData);
        dataField.setDescription(description);

        return dataField;
    }

    public static BeanDataObjectField createDataObjectField(BeanFieldDescriptor beanFieldDescriptor,
                                                            ObjectField objectFieldAnnotation) {
        String name = beanFieldDescriptor.getName();
        String displayName = objectFieldAnnotation.displayName();

        Class<?> refClazz = beanFieldDescriptor.getGetMethod().getReturnType();
        IDataObjectMeta objectMeta = BeanMetaManager.getBeanMeta(refClazz);

        BeanDataObjectField objectField = new BeanDataObjectField(beanFieldDescriptor, name, displayName, objectMeta);
        return objectField;
    }

    public static BeanReferenceField createReferenceField(BeanFieldDescriptor beanFieldDescriptor,
                                                          ReferenceField referenceFieldAnnotation) {
        Class<?> beanClass = beanFieldDescriptor.getBeanClass();

        String name = beanFieldDescriptor.getName();
        String displayName = referenceFieldAnnotation.displayName();
        String dbFieldName = referenceFieldAnnotation.dbFieldName();
        String hostTableName = referenceFieldAnnotation.tableName();
        boolean indexField = referenceFieldAnnotation.indexField();
        int sort = referenceFieldAnnotation.sort();
        String description = referenceFieldAnnotation.description();

        PropertyDescriptor refIdPropertyDescriptor = BeanUtils.getPropertyDescriptor(beanClass,
                beanFieldDescriptor.getPropertyName() + IDataField.ID_FIELD_NAME);
        if (refIdPropertyDescriptor == null) {
            throw ExceptionFactory.createRuntimeException("pisces-core.BeanFieldFactory.createReferenceField-001",
                    beanClass.getName(), name);
        }

        BeanFieldDescriptor refIdFieldDescriptor = new BeanFieldDescriptor(beanClass, refIdPropertyDescriptor);

        String refIdFieldName = name + IDataField.ID_FIELD_NAME;
        String refIdFieldDisplayName = displayName + IDataField.ID_FIELD_NAME;

        BeanDataField refrenceIdField = new BeanDataField(refIdFieldDescriptor, refIdFieldName, refIdFieldDisplayName,
                dbFieldName, hostTableName, false, indexField);
        refrenceIdField.setDescription(description);
        refrenceIdField.setSort(sort);

        // 目前先不组装refMeta，因为表自联问题，基本字段组装完后再组装关联对象
        BeanReferenceField refField = new BeanReferenceField(beanFieldDescriptor, name, displayName, null,
                refrenceIdField);
        return refField;
    }
}
